﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Reflection;
using KylinORM.Data;
using KylinORM.Utils;
using System.Text.RegularExpressions;
using System.Collections;
using KylinORM.Mapper.Base;
using KylinORM.Aspect.Definition;

namespace KylinORM.Mapper
{
    /// <summary>
    /// 简单实体映射器
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class SimpleMapper<T> : MapperBase<T>, ISimpleMapper<T> where T : new()
    {
        /// <summary>
        /// 创建指定实体类型的映射器
        /// </summary>
        protected internal SimpleMapper()
            : base()
        {
        }
        /// <summary>
        /// 创建指定实体的映射器
        /// </summary>
        /// <param name="targetEntity">数据实体</param>
        /// <param name="definitionRule">实体对应映射规则</param>
        protected internal SimpleMapper(T targetEntity, IEntityDefinitionRule definitionRule)
            : base(targetEntity, definitionRule)
        {
        }

        #region ISimpleMapper<T> 成员

        #region 标准查询
        /// <summary>
        /// 查询实体
        /// </summary>
        /// <returns></returns>
        public List<T> Select()
        {
            DataQuery query = this.mapperCommand.GetSelectCommand();
            return TypeConverter.GetEntityList<T>(DataProvider.GetInstance().ExecuteDataTable(query), this);
        }
        /// <summary>
        /// 使用指定查询条件，查询实体
        /// </summary>
        /// <param name="queryEntity">作为查询条件的实体</param>
        /// <returns></returns>
        public List<T> Select(T queryEntity)
        {
            this.Entity = queryEntity;
            return this.Select();
        }

        /// <summary>
        /// 查询实体，仅返回指定的字段
        /// </summary>
        /// <param name="fields">要返回的实体字段列表</param>
        /// <returns></returns>
        public List<T> Select(string fields)
        {
            //将实体字段转换为数据库列名
            List<string> tableFieldNames = new List<string>();
            foreach (string entityFieldName in fields.Split(','))
            {
                if (this.EntityFieldInfos.Keys.Contains(entityFieldName))
                    tableFieldNames.Add(this.EntityFieldInfos[entityFieldName].FieldName);
                else
                    tableFieldNames.Add(entityFieldName);
            }

            DataQuery query = this.mapperCommand.GetSelectCommand(string.Join(",", tableFieldNames.ToArray()), null);
            return TypeConverter.GetEntityList<T>(DataProvider.GetInstance().ExecuteDataTable(query), this);
        }
        /// <summary>
        /// 查询实体，仅返回指定的字段
        /// </summary>
        /// <param name="queryEntity">作为查询条件的实体</param>
        /// <param name="fields">要返回的实体字段列表</param>
        /// <returns></returns>
        public List<T> Select(T queryEntity, string fields)
        {
            this.Entity = queryEntity;
            return this.Select(fields);
        }

        /// <summary>
        /// 查询实体，使用指定的Sql语句
        /// </summary>
        /// <param name="sql">完整Sql语句</param>
        /// <param name="parms">查询参数</param>
        /// <returns></returns>
        public List<T> Select(string sql, params object[] parms)
        {
            DataQuery query = this.mapperCommand.GetSelectCommand(sql, parms);
            return TypeConverter.GetEntityList<T>(DataProvider.GetInstance().ExecuteDataTable(query), this);
        }
        /// <summary>
        /// 查询实体，使用指定的Sql语句
        /// </summary>
        /// <typeparam name="TEntity">返回的数据类型</typeparam>
        /// <param name="sql">完整Sql语句</param>
        /// <param name="parms">查询参数</param>
        /// <returns></returns>
        public List<TEntity> Select<TEntity>(string sql, params object[] parms) where TEntity : new()
        {
            DataQuery query = this.mapperCommand.GetSelectCommand(sql, parms);
            return TypeConverter.GetEntityList<TEntity>(DataProvider.GetInstance().ExecuteDataTable(query));
        }
        #endregion

        #region 主键查询
        /// <summary>
        /// 使用指定的主键值查询
        /// </summary>
        /// <param name="keyValues"></param>
        /// <returns></returns>
        public T Find(params object[] keyValues)
        {
            var primaryFields = this.EntityFieldInfos.Where(d => d.Value.IsPrimaryField == true).ToArray();
            for (int i = 0; i < primaryFields.Length || i < keyValues.Length; i++)
            {
                this[primaryFields[i].Key] = keyValues[i];
            }
            return this.FirstOrDefault();
        }
        #endregion

        #region 分页查询

        /// <summary>
        /// 查询实体并分页，使用默认查询条件
        /// </summary>
        /// <param name="page">页码，从1开始</param>
        /// <param name="itemsPerPage">每页行数</param>
        /// <returns></returns>
        public DataResult<T> SelectPage(int page, int itemsPerPage)
        {
            DataQuery query = this.mapperCommand.GetSelectCommand();
            return this.SelectPage(page, itemsPerPage, query.CommandText, query.Parameters);
        }
        /// <summary>
        /// 使用指定查询条件，查询实体并分页，使用默认查询条件
        /// </summary>
        /// <param name="queryEntity">作为查询条件的实体</param>
        /// <param name="page">页码，从1开始</param>
        /// <param name="itemsPerPage">每页行数</param>
        /// <returns></returns>
        public DataResult<T> SelectPage(T queryEntity, int page, int itemsPerPage)
        {
            this.Entity = queryEntity;
            return this.SelectPage(page, itemsPerPage);
        }

        /// <summary>
        /// 查询实体并分页，使用自定义请求
        /// </summary>
        /// <param name="page">页码，从1开始</param>
        /// <param name="itemsPerPage">每页行数</param>
        /// <param name="sql">完整Sql语句</param>
        /// <param name="parms">查询参数</param>
        /// <returns></returns>
        public DataResult<T> SelectPage(int page, int itemsPerPage, string sql, params object[] parms)
        {
            DataQuery[] queryPage = this.mapperCommand.GetPageCommand(page, itemsPerPage, sql, parms);
            //计算页码
            var result = new DataResult<T>();
            result.CurrentPage = page;
            result.ItemsPerPage = itemsPerPage;
            result.TotalItems = int.Parse(DataProvider.GetInstance().ExecuteScalar(queryPage[1]).ToString());
            result.TotalPages = result.TotalItems / itemsPerPage;
            if ((result.TotalItems % itemsPerPage) != 0)
                result.TotalPages++;

            //获取数据
            result.Items = TypeConverter.GetEntityList<T>(DataProvider.GetInstance().ExecuteDataTable(queryPage[0]), this);

            return result;
        }
        /// <summary>
        /// 查询实体并分页，使用自定义请求
        /// </summary>
        /// <typeparam name="TEntity">返回的数据类型</typeparam>
        /// <param name="page">页码，从1开始</param>
        /// <param name="itemsPerPage">每页行数</param>
        /// <param name="sql">完整Sql语句</param>
        /// <param name="parms">查询参数</param>
        /// <returns></returns>
        public DataResult<TEntity> SelectPage<TEntity>(int page, int itemsPerPage, string sql, params object[] parms) where TEntity : new()
        {
            DataQuery[] queryPage = this.mapperCommand.GetPageCommand(page, itemsPerPage, sql, parms);
            //计算页码
            var result = new DataResult<TEntity>();
            result.CurrentPage = page;
            result.ItemsPerPage = itemsPerPage;
            result.TotalItems = int.Parse(DataProvider.GetInstance().ExecuteScalar(queryPage[1]).ToString());
            result.TotalPages = result.TotalItems / itemsPerPage;
            if ((result.TotalItems % itemsPerPage) != 0)
                result.TotalPages++;

            //获取数据
            result.Items = TypeConverter.GetEntityList<TEntity>(DataProvider.GetInstance().ExecuteDataTable(queryPage[0]));

            return result;
        }
        #endregion

        #region 排序
        private static Regex rxOrderBy = new Regex("( asc| desc|,)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        /// <summary>
        /// 查询实体，使用指定的排序字段
        /// </summary>
        /// <param name="fields">排序字段</param>
        /// <returns></returns>
        public List<T> OrderBy(string fields)
        {
            DataQuery query = this.mapperCommand.GetSelectCommand();
            query.CommandText += " order by " + fields;
            if (!rxOrderBy.IsMatch(fields))
                query.CommandText += " asc";
            return TypeConverter.GetEntityList<T>(DataProvider.GetInstance().ExecuteDataTable(query), this);
        }
        /// <summary>
        /// 使用指定查询条件，查询实体，使用指定的排序字段
        /// </summary>
        /// <param name="queryEntity"></param>
        /// <param name="fields">排序字段</param>
        /// <returns></returns>
        public List<T> OrderBy(T queryEntity, string fields)
        {
            this.Entity = queryEntity;
            return this.OrderBy(fields);
        }

        /// <summary>
        /// 查询实体，使用指定的排序字段
        /// </summary>
        /// <param name="fields">排序字段</param>
        /// <returns></returns>
        public List<T> OrderByDescending(string fields)
        {
            DataQuery query = this.mapperCommand.GetSelectCommand();
            query.CommandText += " order by " + fields;
            if (!rxOrderBy.IsMatch(fields))
                query.CommandText += " desc";
            return TypeConverter.GetEntityList<T>(DataProvider.GetInstance().ExecuteDataTable(query), this);
        }
        /// <summary>
        /// 使用指定查询条件，查询实体，使用指定的排序字段
        /// </summary>
        /// <param name="queryEntity"></param>
        /// <param name="fields">排序字段</param>
        /// <returns></returns>
        public List<T> OrderByDescending(T queryEntity, string fields)
        {
            this.Entity = queryEntity;
            return this.OrderByDescending(fields);
        }
        #endregion

        #endregion

        #region IEnumerable<T> 成员
        /// <summary>
        /// 按当前实体的属性作为查询条件，返回全部数据
        /// </summary>
        /// <returns></returns>
        public virtual IEnumerator<T> GetEnumerator()
        {
            foreach (T entity in this.Select())
                yield return entity;
        }
        /// <summary>
        /// 按当前实体的属性作为查询条件，返回全部数据
        /// </summary>
        /// <returns></returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
        #endregion

        #region ILinqable<T> 成员

        #region 使用当前实体查询

        /// <summary>
        /// 确定序列是否包含任何元素。
        /// </summary>
        /// <returns></returns>
        public bool Any()
        {
            return this.Count() > 0;
        }
        /// <summary>
        /// 通过使用默认的相等比较器对值进行比较返回序列中的非重复元素。
        /// </summary>
        /// <returns></returns>
        public List<T> Distinct()
        {
            return this.Select("DISTINCT *", null);
        }
        /// <summary>
        /// 返回序列中的第一个元素
        /// </summary>
        /// <returns></returns>
        public T First()
        {
            return this.Take(1).First();
        }
        /// <summary>
        /// 返回序列中的第一个元素；如果序列中不包含任何元素，则返回默认值。
        /// </summary>
        /// <returns></returns>
        public T FirstOrDefault()
        {
            return this.Take(1).FirstOrDefault();
        }
        /// <summary>
        /// 返回序列中满足指定条件的唯一元素；如果有多个这样的元素存在，则会引发异常。
        /// </summary>
        /// <returns></returns>
        public T Single()
        {
            return this.Take(1).Single();
        }
        /// <summary>
        /// 返回序列中满足指定条件的唯一元素；如果这类元素不存在，则返回默认值；如果有多个元素满足该条件，此方法将引发异常。
        /// </summary>
        /// <returns></returns>
        public T SingleOrDefault()
        {
            return this.Take(1).SingleOrDefault();
        }
        /// <summary>
        /// 从序列的开头返回指定数量的连续元素。
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public List<T> Take(int count)
        {
            return this.Fetch(null, count);
        }
        /// <summary>
        /// 跳过序列中指定数量的元素，然后返回剩余的元素。
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public List<T> Skip(int count)
        {
            return this.Fetch(count, null);
        }
        /// <summary>
        /// 跳过序列中指定数量的元素，然后返回指定数量的连续元素。
        /// </summary>
        /// <param name="skip"></param>
        /// <param name="take"></param>
        /// <returns></returns>
        public List<T> Fetch(int? skip, int? take)
        {
            DataQuery query = this.mapperCommand.GetSelectCommand(skip ?? 0, take ?? int.MaxValue);
            return TypeConverter.GetEntityList<T>(DataProvider.GetInstance().ExecuteDataTable(query), this);
        }
        /// <summary>
        /// 统计实体数量
        /// </summary>
        /// <returns></returns>
        public int Count()
        {
            DataQuery query = this.mapperCommand.GetCountCommand();
            return int.Parse(DataProvider.GetInstance().ExecuteScalar(query).ToString());
        }
        #endregion

        #region 使用指定实体查询

        /// <summary>
        /// 确定序列是否包含任何元素。
        /// </summary>
        /// <returns></returns>
        public bool Any(T queryEntity)
        {
            this.Entity = queryEntity;
            return this.Any();
        }
        /// <summary>
        /// 通过使用默认的相等比较器对值进行比较返回序列中的非重复元素。
        /// </summary>
        /// <returns></returns>
        public List<T> Distinct(T queryEntity)
        {
            this.Entity = queryEntity;
            return this.Distinct();
        }
        /// <summary>
        /// 返回序列中的第一个元素
        /// </summary>
        /// <returns></returns>
        public T First(T queryEntity)
        {
            this.Entity = queryEntity;
            return this.First();
        }
        /// <summary>
        /// 返回序列中的第一个元素；如果序列中不包含任何元素，则返回默认值。
        /// </summary>
        /// <returns></returns>
        public T FirstOrDefault(T queryEntity)
        {
            this.Entity = queryEntity;
            return this.FirstOrDefault();
        }
        /// <summary>
        /// 返回序列中满足指定条件的唯一元素；如果有多个这样的元素存在，则会引发异常。
        /// </summary>
        /// <returns></returns>
        public T Single(T queryEntity)
        {
            this.Entity = queryEntity;
            return this.Single();
        }
        /// <summary>
        /// 返回序列中满足指定条件的唯一元素；如果这类元素不存在，则返回默认值；如果有多个元素满足该条件，此方法将引发异常。
        /// </summary>
        /// <returns></returns>
        public T SingleOrDefault(T queryEntity)
        {
            this.Entity = queryEntity;
            return this.SingleOrDefault();
        }
        /// <summary>
        /// 从序列的开头返回指定数量的连续元素。
        /// </summary>
        /// <param name="queryEntity"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public List<T> Take(T queryEntity, int count)
        {
            this.Entity = queryEntity;
            return this.Take(count);
        }
        /// <summary>
        /// 跳过序列中指定数量的元素，然后返回剩余的元素。
        /// </summary>
        /// <param name="queryEntity"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public List<T> Skip(T queryEntity, int count)
        {
            this.Entity = queryEntity;
            return this.Skip(count);
        }
        /// <summary>
        /// 跳过序列中指定数量的元素，然后返回指定数量的连续元素。
        /// </summary>
        /// <param name="queryEntity"></param>
        /// <param name="skip"></param>
        /// <param name="take"></param>
        /// <returns></returns>
        public List<T> Fetch(T queryEntity, int? skip, int? take)
        {
            this.Entity = queryEntity;
            return this.Fetch(skip, take);
        }
        /// <summary>
        /// 统计实体数量
        /// </summary>
        /// <returns></returns>
        public int Count(T queryEntity)
        {
            this.Entity = queryEntity;
            return this.Count();
        }
        #endregion

        #endregion

    }

    /// <summary>
    /// 简单实体映射器工厂
    /// </summary>
    public abstract class SimpleMapper : MapperBase
    {
        /// <summary>
        /// 创建指定实体的映射器
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <returns></returns>
        public static ISimpleMapper<T> Inject<T>() where T : new()
        {
            return new SimpleMapper<T>(default(T), null);
        }
        /// <summary>
        /// 创建指定实体的映射器
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="entity">this</param>
        /// <param name="definitionRule">实体对应映射规则</param>
        /// <returns></returns>
        public static ISimpleMapper<T> Inject<T>(T entity, IEntityDefinitionRule definitionRule) where T : new()
        {
            return new SimpleMapper<T>(entity, definitionRule);
        }

    }
}